#include "glare.gles2.Driver.h"
#include "glare.gles2.GpuResourceFactory.h"
#include "glare.gles2.DrawContext.h"
#include "glare.gles2.RenderWindow.h"
#include "glare.gles2.ShaderFactory.h"
#include "glare.gles2.DrawStateFactory.h"

namespace Glare {

	string GLES2Driver::Name = "GLES2";

	GLES2Driver::GLES2Driver()
		: _gpu_resources(NULL)
		, _gpu_shaders(NULL)
		, _draw_states(NULL)
	{
		static const GpuPrimitive::Type types[] = 
		{
			GpuPrimitive::TriangleList,
			GpuPrimitive::TriangleStrip
		};

		std::list<GpuPrimitive::Type> supported_primitives(types, types + sizeof(types) / sizeof(types[0]));
		_driver_caps.SetSupportedPrimitives(supported_primitives);

		_gpu_resources = new GLES2GpuResourceFactory(this);
		_gpu_shaders = new GLES2ShaderFactory(this);
		_draw_states = new GLES2DrawStateFactory(this);

		_immediate_draw_context = new GLES2DrawContext(this);
	}
	
	GLES2Driver::~GLES2Driver()
	{
		delete _draw_states;
		_draw_states = NULL;

		delete _gpu_shaders;
		_gpu_shaders = NULL;

		delete _gpu_resources;
		_gpu_resources = NULL;

		delete _immediate_draw_context;
		_immediate_draw_context = NULL;
	}

	GpuResourceFactory* GLES2Driver::GetGpuResourceFactory() const
	{
		return _gpu_resources;
	}

	ShaderFactory* GLES2Driver::GetShaderFactory() const
	{
		return _gpu_shaders;
	}

	DrawStateFactory* GLES2Driver::GetDrawStateFactory() const
	{
		return _draw_states;
	}

	std::string& GLES2Driver::GetName() const
	{
		return Name;
	}

	RenderWindow* GLES2Driver::CreateRenderWindow(PlatformWindow* platform_window)
	{
		return new GLES2RenderWindow(this, platform_window);
	}

	void GLES2Driver::DestroyRenderWindow(RenderWindow* render_window)
	{
		delete render_window;
	}

	const DriverStage::Type GLES2Driver::GetSupportedStages() const
	{
		return DriverStage::OutputMerger;
	}

	const DriverCapabilities& GLES2Driver::GetCapabilities() const
	{
		return _driver_caps;
	}

	DrawContext* GLES2Driver::GetImmediateDrawContext() const
	{
		return _immediate_draw_context;
	}

	DrawContext* GLES2Driver::CreateDrawContext()
	{
		GLES2DrawContext* draw_context = new GLES2DrawContext(this);
		return draw_context;
	}

	void GLES2Driver::DestroyDrawContext(DrawContext* draw_context)
	{
		delete draw_context;
	}

	GLES2ShaderFactory* GLES2Driver::GetGLES2ShaderFactory() const
	{
		return _gpu_shaders;
	}

}
